package com.mygame.gateway.server.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.mygame.common.model.AccountToken;
import com.mygame.common.utils.NettyUtils;
import com.mygame.common.utils.TopicUtil;
import com.xinyue.game.common.config.GameServerCommonConfig;
import com.xinyue.mqsystem.mq.GameMQTemplate;
import com.xinyue.network.message.stream.ServiceMessageHeader;
import com.xinyue.network.message.stream.TransferMessage;
import com.xinyue.server.balance.PlayerServiceInstance;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.CompositeByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class DispatchGameMessageHandler extends ChannelInboundHandlerAdapter {
    private PlayerServiceInstance playerServiceInstance;// 注入业务服务管理类，从这里获取负载均衡的服务器信息
    private GameServerCommonConfig gameServerCommonConfig;
    private AccountToken accountToken;
    private GameMQTemplate gameMQTemplate;
    private NacosDiscoveryProperties nacosDiscoveryProperties;
    //业务服务接收消息的topic前缀
    private static final String BusinessTopicPrefix = "XinyueBusinessTopic";
    private static Logger logger = LoggerFactory.getLogger(DispatchGameMessageHandler.class);

    public DispatchGameMessageHandler(ApplicationContext applicationContext) {
        this.playerServiceInstance = applicationContext.getBean(PlayerServiceInstance.class);
        this.gameMQTemplate = applicationContext.getBean(GameMQTemplate.class);
        this.gameServerCommonConfig = applicationContext.getBean(GameServerCommonConfig.class);
        this.nacosDiscoveryProperties = applicationContext.getBean(NacosDiscoveryProperties.class);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        TransferMessage transferMessage = (TransferMessage) msg;
        if (accountToken == null) {// 如果首次通信，获取验证信息
            ConfirmHandler confirmHandler = (ConfirmHandler) ctx.channel().pipeline().get("ConfirmHandler");
            accountToken = confirmHandler.getAccountToken();
        }
        String clientIp = NettyUtils.getRemoteIP(ctx.channel());
        // 转化为服务消息包头
        ServiceMessageHeader serviceMessageHeader = new ServiceMessageHeader();
        BeanUtils.copyProperties(transferMessage.getHeader(), serviceMessageHeader);
        serviceMessageHeader.getAttr().setClientIp(clientIp);
        serviceMessageHeader.getAttr().setAccountId(accountToken.getAccountId());
        dispatchMessage(serviceMessageHeader, transferMessage.getBody());
    }

    public void dispatchMessage(ServiceMessageHeader header, ByteBuf body) throws Exception {
        long playerId = accountToken.getPlayerId();
        int serviceId = header.getServiceId();
        String namespace = nacosDiscoveryProperties.getNamespace();
        int toServerId = playerServiceInstance.selectServerId(playerId, serviceId, namespace);
        if (toServerId == 0) {
            logger.error("找不到playerId {},serviceId {} 对应的目标服务器", playerId, serviceId);
        }

        header.setToServerId(toServerId);
        header.setFromServerId(gameServerCommonConfig.getLocalServerId());
        header.setPlayerId(playerId);

        String topic = TopicUtil.generateTopic(namespace, BusinessTopicPrefix, toServerId);// 动态创建与业务服务交互的消息总线Topic
        ByteBuf totalSizeBuf = Unpooled.buffer(4);
        
        ByteBuf headerBuf = header.write();
        int messageTotalSize = 4 + headerBuf.readableBytes();
        CompositeByteBuf compositeByteBuf = Unpooled.compositeBuffer();
      
        if (body != null) {
        	messageTotalSize += body.readableBytes();
        }
        totalSizeBuf.writeInt(messageTotalSize);
        compositeByteBuf.addComponent(true,totalSizeBuf);
        compositeByteBuf.addComponent(true, headerBuf);
        if (body != null) {
            compositeByteBuf.addComponent(true, body);
        }
        
        byte[] value = new byte[compositeByteBuf.readableBytes()];
        compositeByteBuf.readBytes(value);
        gameMQTemplate.syncSendOrderly(topic, value, playerId);
        logger.debug("发送到{} Topic 消息成功->{}", topic, header);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        logger.error("服务器异常，连接{}断开", ctx.channel().id().asShortText(), cause);
    }
}
